package org.shj.basic.extendclass

abstract class Person{
  val id: Int  //没有初始化，这是一个带有抽象的 getter 方法的抽象字段
  var name: String //抽象字段，带有抽象的 getter 和 setter 方法
  def age: Int // 抽象方法，不需要加 abstract, 方法主体为空就行， 子类实现时，不需要加 override 关键字
}

class Point(val cx : Int, val cy: Int){
  var x = cx
  private var y = cy
  
  def move(dx : Int, dy : Int){
    x += dx
    y += dy
    println("x=" + x + "; y=" + y)
  }
  
  override def toString = getClass.getName + " x=" + x + "; y=" + y
}

/**
 * 父类中除private修饰的变量外，子类均可以直接使用，想要覆盖父类中的变量，父类中的变量必须是 val 修饰的变量，
 * 且子类必须申明 override val
 * 规则：
 * 1. def 只能重写另一个 def
 * 2. val 只能重写另一个 val 或不带参数的 def
 * 3. var 只能重写另一个抽象的 var
 */
class Location(override val cx : Int, override val cy : Int, val cz : Int) extends Point(cx,cy){
  //var x = cx  //此句有问题，编译器提示需要加上 override 才能覆盖父类的属性
  //override var x = cx  //按照上面的提示，仍然报错，var 修饰的是可变变量，无法覆盖。
  x = cx; //此变量其实是 Point 中的变量
  var y = cy; //父类中的y必须申明为private的，子类中才可以取相同的变量名
  var z = cz;
  
  def move(dx : Int, dy : Int, dz : Int){
    x += dx
    y += dy
    z += dz
    println("x=" + x + "; y=" + y + "; z=" + z)
  }
  
  override def toString = super.toString + "; z=" + z
}

object PropertyOverride {
  def main(args: Array[String]): Unit = {
    val loc = new Location(10,20,30)
    loc.move(1,2,3)
    loc.move(5, 6) //从结果可以看出来， x 一直在累加，而 y 则在各自的作用范围内，互不影响
    
    println(loc)
  }
}